Everything Else That Was Already Here
Next let’s plot the moments where spatial referencing happens. Those are frames
- 198 to 223
- 265 to 288
- 352 to 380
The max gazepointindex is around 2580. At 120 Hz, that’s 21.5 seconds which is just right, that’s the length. Let’s go ahead and convert gazepointindex to seconds.
So we just have to convert frames to gazepointindex. The video is a total of 536 frames, at 25 FPS that’s 21.5 seconds. 535/25 = 21.5, so we divide all those frames by 25.
- 7.92s to 8.92s
- 10.6s to 11.52s
- 14.08s to 15.2s
And plot those!
data <- data %>%
rowwise() %>%
mutate(secs = gaze_point_index/120)
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
geom_line() +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
theme_bw()

Maybe easier if we separate groups of signers.
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
geom_line(alpha = 0.5) +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(maingroup ~ .) +
theme_bw() +
guides(color = FALSE)

Next, we’re going to add AOI position information. We’re going to pull in information on signers’ right hand position (and then apply the same idea to other body parts). I successfully wrote a function called get_xy_timestamp to do this! Yay. I’m chuffed, as the British would say.
Let’s try this on Stephanie’s data. Let’s see if we can find a correlation between any of those and the eye gaze y-position.
# We add one more row to the xy_timestamp data to align it with the end of the eye gaze data.
rhand <- get_xy_timestamp("aoi_position/Cindy_bears_FW_Position of Right Hand.txt") %>%
add_row(sec = 21.5, x = 640.16, y = 1055.97)
lhand <- get_xy_timestamp("aoi_position/Cindy_bears_FW_Position of Left Hand.txt") %>%
add_row(sec = 21.5, x = 703.74, y = 1058.39)
mouth <- get_xy_timestamp("aoi_position/Cindy_bears_FW_Position of mouth small.txt") %>%
add_row(sec = 21.5, x = 656.37, y = 373.99)
# Get Stephanie's data
steph <- filter(data, name == "Stephanie")
steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
# geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
# geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
# annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
# annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
# annotate("text", label = "Mouth", x = 3, y = 200, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
# geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
# annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
# annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 250, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
# geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
# annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 250, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 250, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

Now let’s work on correlations. First, our AOI vectors are not the same size as our eye gaze vectors, and the x/y position is irregularly spaced across time (irregularly spaced key frames).
# The following code will "expand" the rhand data vectors to fit the length of Stephanie's data vectors.
time_index <- steph$secs
closest <- function(x){
which.min(abs(time_index-x))
}
index_loc <- map_int(rhand$sec, closest)
rhand <- cbind(rhand, time_index[index_loc]) %>%
select(-sec) %>%
rename(sec = "time_index[index_loc]") %>%
select(sec, x, y)
rhand_full <- select(steph, secs) %>%
rename(sec = secs) %>%
left_join(rhand) %>%
fill(x) %>%
fill(y) %>%
slice(1:(nrow(.)-1))
Joining, by = "sec"
rhand_full <- rhand_full %>%
filter(sec < rhand$sec[172]) %>%
filter(sec >= rhand$sec[2])
steph <- steph %>%
filter(secs < rhand$sec[172]) %>%
filter(secs >= rhand$sec[2])
a <- rhand_full$y
a <- a[1:length(a)-1] # Shorten it by one element
b <- steph$y
# Then run correlations
cor(a,b, use = "complete.obs") # basic correlation
[1] 0.2894728
that <- ccf(a,b, lag.max = 400, type = "correlation", na.action = na.pass, plot = T) # auto-correlation

Let’s separate out individual signers.
make_signer_plots <- function(groupname, line_color) {
data %>%
filter(maingroup == groupname) %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse() +
geom_line(alpha = 1, color = line_color) +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 200, color = "black", alpha = 0.5) +
facet_grid(name ~ .) +
ggtitle(groupname) +
theme_bw()
}
make_signer_plots("DeafEarly", "red")

make_signer_plots("DeafLate", "dark green")

make_signer_plots("HearingLate", "blue")

make_signer_plots("HearingNovice", "purple")

Okay so with Early ASL obviously very steady gaze. NoviceASL has lot of downshifts. Some align with spatial referencing, some do not. We need more of them (let’s look at other stories w better data).
Midas Forward
# Get Midas data
data <- read_csv("../Adult Data/rawdata/midasfw.csv") %>%
clean_names() %>%
rename(y = gaze_point_y_mc_spx,
language = language_value,
name = participant_name,
group = group_value)
# Pull clean names and join to data
cleannames <- read_csv("partnames.csv") %>%
distinct() %>%
rename(name = participant)
data <- data %>% left_join(cleannames, by = "name") %>%
select(-name) %>%
rename(name = new_participant) %>%
filter(!is.na(name))
# Pull final group assignments and join to data
cleangroups <- read_csv("finaldataset.csv") %>%
select(participant, maingroup) %>%
rename(name = participant) %>%
distinct()
data <- data %>% left_join(cleangroups, by = "name") %>%
select(-group)
# Let's find out who was NOT included in Three Bears
excluded <- read_csv("finaldataset.csv") %>%
select(participant, maingroup, story, direction, eye_exclude) %>%
filter(story == "KingMidas" & direction == "forward") %>%
rename(name = participant) %>%
select(name, eye_exclude)
data <- data %>% left_join(excluded, by = "name") %>%
filter(!eye_exclude) %>%
filter(!is.na(eye_exclude))
data %>% select(name, maingroup) %>% distinct()
Now let’s graph!!
Hm. One person seems wrong.
data %>%
ggplot(aes(x = gaze_point_index, y = y, color = maingroup, group = name)) + geom_line() + scale_y_reverse()

Okay it’s Jesse’s data that seems off. We’ll remove him for now and come back to it, figure out why.
data %>% filter(gaze_point_index > 30000) %>% select(name) %>% distinct() %>% head()
data <- data %>%
filter(name != "Jesse")
data %>%
ggplot(aes(x = gaze_point_index, y = y, color = maingroup, group = name)) + geom_line() +
scale_y_reverse() +
scale_x_continuous(limits = c(0,4500))

Next let’s plot the moments where spatial referencing happens. Those are frames
- 248 to 427
- 460 to 508
- 512 to 560
Like before, we’ll convert gazepointindex to seconds (by dividing 120) and all frames to seconds (by dividing 25).
- 9.92s to 17.08s
- 18.4s to 20.32s
- 20.48s to 22.4s
data <- data %>%
rowwise() %>%
mutate(secs = gaze_point_index/120)
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line() +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red")

Maybe easier if we separate groups of signers.
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 0.5) +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(maingroup ~ .)

Individual signers.
data %>%
filter(maingroup == "DeafEarly") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_x_continuous(limits = c(0, 37.5)) +
scale_y_reverse() +
geom_line(alpha = 1, color = "red") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("DeafEarly")

data %>%
filter(maingroup == "DeafLate") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "dark green") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("DeafLate")

data %>%
filter(maingroup == "HearingLate") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "blue") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("HearingLate")

data %>%
filter(maingroup == "HearingNovice") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "purple") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("HearingNovice")

LS0tCnRpdGxlOiAiU3BhdGlhbCBSZWZlcmVuY2luZyIKYXV0aG9yOiAiQWRhbSBTdG9uZSwgUGhEIgpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlbS0lZC0lWSIpYCcKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRoZW1lOiBwYXBlcgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OiB5ZXMKLS0tCgpgYGB7cn0KIyMgUmVhZHMgaW4gQU9JIHBvc2l0aW9uIHRleHQgZmlsZXMgZnJvbSBUb2lpCiMjIFdpbGwgcmV0dXJuIHRpYmJsZSBvZiBjb2x1bW5zIHNlYywgeCwgeSwgd2l0aCByb3dzIGZvciBlYWNoIHRpbWVzdGFtcC9BT0kgcG9zaXRpb24KCmdldF94eV90aW1lc3RhbXAgPC0gZnVuY3Rpb24oeil7Cgp4IDwtIHJlYWRfbGluZXMoeikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcm93aWRfdG9fY29sdW1uKCJJRCIpCgojIHB1bGwgb3V0IHRpbWVzdGFtcCByb3dzCnRpbWVzdGFtcHMgPC0geCAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdCh2YWx1ZSwgInRpbWVzdGFtcCIpKSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoInRocm93IiwidGltZXN0YW1wIiksIHNlcCA9ICIgPSAiKSAlPiUKICBzZXBhcmF0ZSh0aW1lc3RhbXAsIGludG8gPSBjKCJvbmUiLCJ0d28iLCJzZWMiKSwgc2VwID0gIjoiKSAlPiUKICBzZWxlY3Qoc2VjKSAlPiUKICBtdXRhdGUoc2VjID0gYXMubnVtZXJpYyhzZWMpKQoKIyBGaW5kIEFPSSBjb29yZGluYXRlIHJvd3MKeHlzIDwtIHggJT4lCiAgbXV0YXRlKGZpbmQgPSBzdHJfZGV0ZWN0KHZhbHVlLCAiWFx0WSIpKQoKIyBmaXJzdCB2ZXJ0ZXggKDIgcm93cyBhZnRlciBlYWNoICJYWSIgbGluZSkKeHlzX3JvdyA8LSB3aGljaCh4eXMkZmluZCkgKyAyCgp4eTEgPC0geCAlPiUKICBmaWx0ZXIoSUQgJWluJSB4eXNfcm93KSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoIngxIiwieTEiKSwgc2VwID0gIlx0IikgJT4lCiAgc2VsZWN0KC1JRCkKCiMgb3Bwb3NpdGUgdmVydGV4ICgyIG1vcmUgcm93cyBkb3duKQp4eXNfcm93IDwtIHh5c19yb3cgKyAyCgp4eTIgPC0geCAlPiUKICBmaWx0ZXIoSUQgJWluJSB4eXNfcm93KSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoIngyIiwieTIiKSwgc2VwID0gIlx0IikgJT4lCiAgc2VsZWN0KC1JRCkKCiMgTm93IGdldCBhdmVyYWdlIFhZIHBvc2l0aW9uIHBlciB0aW1lc3RhbXAKeHlzIDwtIGNiaW5kKHRpbWVzdGFtcHMsIHh5MSwgeHkyKSAlPiUKICBtdXRhdGVfYWxsKGFzLm51bWVyaWMpICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUoeCA9IG1lYW4oeDEseDIpLAogICAgICAgICB5ID0gbWVhbih5MSwgeTIpKSAlPiUKICBzZWxlY3Qoc2VjLCB4LCB5KQp9CmBgYAoKTGV0J3MgZ2l2ZSB0aGlzIGEgc2hvdCEhCgojIFRocmVlIEJlYXJzIEZvcndhcmQgCkZpcnN0IGxldCdzIHNlZSB3aG8ncyBpbiBvdXIgZGF0YXNldC4gVGhpcyBpcyBUZXN0IDEgLSAzIEJlYXJzIC0gRm9yd2FyZC4gV2UncmUgcHVsbGluZyBjbGVhbmVkLXVwIG5hbWVzIGFuZCBhc3NpZ25lZCBncm91cHMgZnJvbSBvdXIgZmluYWwgZGF0YXNldCB0aGF0IHdlIHVzZWQgaW4gb3VyIEFPSSBhbmFseXNpcy4gVGhlbiB3ZSBhcmUgcmVtb3ZpbmcgcGFydGljaXBhbnRzIHdob3NlIFRocmVlIEJlYXJzIEZvcndhcmQgc3Rvcnkgd2Fzbid0IGluY2x1ZGVkIGluIG91ciBBT0kgYW5hbHlzaXMgZHVlIHRvIDwyNSUgbG9va2luZyB0aW1lIG9yIG90aGVyIHJlYXNvbnMuIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkob3Blbnhsc3gpCmxpYnJhcnkoamFuaXRvcikKCiMgR2V0IFRocmVlIEJlYXJzIGRhdGEKZGF0YSA8LSByZWFkLnhsc3goIlRlc3QxX0NpbmR5X2JlYXJzX0ZXX0V4YW1pbmUgZm9yIFNwYXRpYWwgUmVmZXJlbmNpbmcueGxzeCIpICU+JQogIGNsZWFuX25hbWVzKCkgJT4lCiAgcmVuYW1lKHkgPSBnYXplX3BvaW50X3lfbWNfc3B4LAogICAgICAgICBsYW5ndWFnZSA9IGxhbmd1YWdlX3ZhbHVlLAogICAgICAgICBuYW1lID0gcGFydGljaXBhbnRfbmFtZSwKICAgICAgICAgZ3JvdXAgPSBncm91cF92YWx1ZSkKCiMgUHVsbCBjbGVhbiBuYW1lcyBhbmQgam9pbiB0byBkYXRhIChhbmQgYWRkIExhdXJhMiBmb3IgTGF1cmEgKG1pc3Npbmcgc3RvcmllcykpCmNsZWFubmFtZXMgPC0gcmVhZF9jc3YoInBhcnRuYW1lcy5jc3YiKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpICU+JQogIGZpbHRlcihuYW1lICE9ICJMYXVyYTIiKQoKZGF0YSA8LSBkYXRhICU+JSAKICBsZWZ0X2pvaW4oY2xlYW5uYW1lcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtbmFtZSkgJT4lCiAgcmVuYW1lKG5hbWUgPSBuZXdfcGFydGljaXBhbnQpICU+JQogIGZpbHRlcighaXMubmEobmFtZSkpCgojIFB1bGwgZmluYWwgZ3JvdXAgYXNzaWdubWVudHMgYW5kIGpvaW4gdG8gZGF0YQpjbGVhbmdyb3VwcyA8LSByZWFkX2NzdigiZmluYWxkYXRhc2V0LmNzdiIpICU+JQogIHNlbGVjdChwYXJ0aWNpcGFudCwgbWFpbmdyb3VwKSAlPiUKICByZW5hbWUobmFtZSA9IHBhcnRpY2lwYW50KSAlPiUKICBkaXN0aW5jdCgpCgpkYXRhIDwtIGRhdGEgJT4lIGxlZnRfam9pbihjbGVhbmdyb3VwcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtZ3JvdXApCgojIExldCdzIGZpbmQgb3V0IHdobyB3YXMgTk9UIGluY2x1ZGVkIGluIFRocmVlIEJlYXJzCmV4Y2x1ZGVkIDwtIHJlYWRfY3N2KCJmaW5hbGRhdGFzZXQuY3N2IikgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50LCBtYWluZ3JvdXAsIHN0b3J5LCBkaXJlY3Rpb24sIGV5ZV9leGNsdWRlKSAlPiUKICBmaWx0ZXIoc3RvcnkgPT0gIkdvbGRpbG9ja3MiICYgZGlyZWN0aW9uID09ICJmb3J3YXJkIikgJT4lCiAgcmVuYW1lKG5hbWUgPSBwYXJ0aWNpcGFudCkgJT4lCiAgc2VsZWN0KG5hbWUsIGV5ZV9leGNsdWRlKQoKZGF0YSA8LSBkYXRhICU+JSBsZWZ0X2pvaW4oZXhjbHVkZWQsIGJ5ID0gIm5hbWUiKSAlPiUKICBmaWx0ZXIoIWV5ZV9leGNsdWRlKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGV5ZV9leGNsdWRlKSkKCmRhdGEgJT4lIHNlbGVjdChuYW1lLCBtYWluZ3JvdXApICU+JSBkaXN0aW5jdCgpCmBgYAoKTm93IGxldCdzIGdyYXBoISEgCgpNZXNzeSwgSSBrbm93LCBidXQgYWxyZWFkeSB3ZSBjYW4gc2VlIHNvbWUgSGVhcmluZ05vdmljZSBoYXMgYmlnIHNoaWZ0cyBkb3dud2FyZC4gQW5kIHNvbWUgSGVhcmluZ0xhdGUgdG9vLgoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIGdlb21fbGluZSgpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzCgpOZXh0LCBsZXQncyBtYWtlIGdyb3VwIGF2ZXJhZ2VzLiAKCmBgYHtyfQphdmVyYWdlZF95IDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCBnYXplX3BvaW50X2luZGV4KSAlPiUKICBzdW1tYXJpc2UoeV9tZWFuID0gbWVhbih5LCBuYS5ybSA9IFQpLAogICAgICAgICAgICB5X3NkID0gc2QoeSwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmF2ZXJhZ2VkX3kgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tZWFuLCBjb2xvciA9IG1haW5ncm91cCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIAogICAgICAgICAgICAgICAgICB5bWluID0geV9tZWFuLXlfc2UsIAogICAgICAgICAgICAgICAgICB5bWF4ID0geV9tZWFuK3lfc2UsCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBtYWluZ3JvdXApLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCkpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKCJtYWluZ3JvdXAiKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzIFdpdGggU21vb3RoaW5nCgpTbyBJJ2xsIGJhY2sgdXAgYW5kIHNtb290aCBlYWNoIHBlcnNvbidzIGRhdGEgdXNpbmcgYSBtb3ZpbmcgYXZlcmFnZSB3aW5kb3cgb2Ygc3BhbiA9IDUuIFRha2VuIGZyb20gb3VyIGFkdWx0IG1hbnVzY3JpcHQgd2hpY2ggaGFkIHRoaXM6IAoKPiBUaGUgZGF0YSB3ZXJlIHRoZW4gc21vb3RoZWQgd2l0aCBhIHN0YW5kYXJkIG1vdmluZyBhdmVyYWdlIG5vaXNlIHJlZHVjdGlvbiBhbGdvcml0aG0gKHdpbmRvdyBzaXplID0gNSBzYW1wbGVzKSB3aGljaCBhY3RzIGFzIGEgbG93LXBhc3MgZmlsdGVyIHRoYXQgcmVkdWNlcyB0aGUgaW5mbHVlbmNlIG9mIG1pY3Jvc2FjY2FkZXMsIGJsaW5rcywgYW5kIGxhcmdlIGRhdGEgZ2FwcyAoYmFzZWQgb24gWWFyYnVzLCAxOTY3KS4gCgpUaGUgYmVsb3cgY2hhcnQgc2hvd3MgQWRhbSdzIGRhdGEsIGJsdWUgaXMgdW5zbW9vdGhlZCBhbmQgcmVkIGlzIHNtb290aGVkLiAKCgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KG1haW5ncm91cCwgcmVjb3JkaW5nX25hbWUpICU+JQogIG11dGF0ZSh5X21hID0gUmNwcFJvbGw6OnJvbGxfbWVhbih5LCBuID0gNSwgZmlsbCA9IDApKQoKZGF0YSAlPiUKICBmaWx0ZXIocmVjb3JkaW5nX25hbWUgPT0gIkFkYW1fR29vZCIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuMjUsIHNpemUgPSAwLjUpICsKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tYSksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjIpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg0NzUsIDMyNSkpICsKICB0aGVtZV9idygpCmBgYAoKU28gdGhhdCdzIG5pY2UuIExldCdzIGdvIGRvIGdyb3VwIGF2ZXJhZ2VzIGFnYWluLiAKCmBgYHtyfQphdmVyYWdlZF95IDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCBnYXplX3BvaW50X2luZGV4KSAlPiUKICBzdW1tYXJpc2UoeV9tZWFuID0gbWVhbih5X21hLCBuYS5ybSA9IFQpLAogICAgICAgICAgICB5X3NkID0gc2QoeV9tYSwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmF2ZXJhZ2VkX3kgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tZWFuLCBjb2xvciA9IG1haW5ncm91cCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIAogICAgICAgICAgICAgICAgICB5bWluID0geV9tZWFuLXlfc2UsIAogICAgICAgICAgICAgICAgICB5bWF4ID0geV9tZWFuK3lfc2UsCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBtYWluZ3JvdXApLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCkpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKCJtYWluZ3JvdXAiKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKCmF2ZXJhZ2VkX3kgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkVhcmx5IiB8IG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHlfbWVhbiwgY29sb3IgPSBtYWluZ3JvdXApKSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCAKICAgICAgICAgICAgICAgICAgeW1pbiA9IHlfbWVhbi15X3NlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IHlfbWVhbit5X3NlLAogICAgICAgICAgICAgICAgICBmaWxsID0gbWFpbmdyb3VwKSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg3MDAsMzAwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzIFdpdGggTW9yZSBTbW9vdGhpbmcKCk1heWJlIHdlIHNob3VsZCBzbW9vdGggZXZlbiBtb3JlLiBTYW1wbGUgc2l6ZSA9IDEwISAKCmBgYHtyfQpkYXRhIDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCByZWNvcmRpbmdfbmFtZSkgJT4lCiAgbXV0YXRlKHlfbWEyID0gUmNwcFJvbGw6OnJvbGxfbWVhbih5LCBuID0gMTAsIGZpbGwgPSAwKSkKCiMgZGF0YSAlPiUKIyAgIGZpbHRlcihyZWNvcmRpbmdfbmFtZSA9PSAiQWRhbV9Hb29kIikgJT4lCiMgICBnZ3Bsb3QoKSArCiMgICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuMjUsIHNpemUgPSAwLjUpICsKIyAgIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21hMiksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjIpICsKIyAgIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDQ3NSwgMzI1KSkgKwojICAgdGhlbWVfYncoKQoKYXZlcmFnZWRfeSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KG1haW5ncm91cCwgZ2F6ZV9wb2ludF9pbmRleCkgJT4lCiAgc3VtbWFyaXNlKHlfbWVhbiA9IG1lYW4oeV9tYTIsIG5hLnJtID0gVCksCiAgICAgICAgICAgIHlfc2QgPSBzZCh5X21hMiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmF2ZXJhZ2VkX3kgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tZWFuLCBjb2xvciA9IG1haW5ncm91cCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIAogICAgICAgICAgICAgICAgICB5bWluID0geV9tZWFuLXlfc2UsIAogICAgICAgICAgICAgICAgICB5bWF4ID0geV9tZWFuK3lfc2UsCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBtYWluZ3JvdXApLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCkpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKCJtYWluZ3JvdXAiKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKCmF2ZXJhZ2VkX3kgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkVhcmx5IiB8IG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHlfbWVhbiwgY29sb3IgPSBtYWluZ3JvdXApKSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCAKICAgICAgICAgICAgICAgICAgeW1pbiA9IHlfbWVhbi15X3NlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IHlfbWVhbit5X3NlLAogICAgICAgICAgICAgICAgICBmaWxsID0gbWFpbmdyb3VwKSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg3MDAsMzAwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEV2ZXJ5dGhpbmcgRWxzZSBUaGF0IFdhcyBBbHJlYWR5IEhlcmUKCk5leHQgbGV0J3MgcGxvdCB0aGUgbW9tZW50cyB3aGVyZSBzcGF0aWFsIHJlZmVyZW5jaW5nIGhhcHBlbnMuIFRob3NlIGFyZSBmcmFtZXMKCjEuIDE5OCB0byAyMjMKMS4gMjY1IHRvIDI4OAoxLiAzNTIgdG8gMzgwCgpUaGUgbWF4IGdhemVwb2ludGluZGV4IGlzIGFyb3VuZCAyNTgwLiBBdCAxMjAgSHosIHRoYXQncyAyMS41IHNlY29uZHMgd2hpY2ggaXMganVzdCByaWdodCwgdGhhdCdzIHRoZSBsZW5ndGguIExldCdzIGdvIGFoZWFkIGFuZCBjb252ZXJ0IGdhemVwb2ludGluZGV4IHRvIHNlY29uZHMuICAKClNvIHdlIGp1c3QgaGF2ZSB0byBjb252ZXJ0IGZyYW1lcyB0byBnYXplcG9pbnRpbmRleC4gVGhlIHZpZGVvIGlzIGEgdG90YWwgb2YgNTM2IGZyYW1lcywgYXQgMjUgRlBTIHRoYXQncyAyMS41IHNlY29uZHMuIDUzNS8yNSA9IDIxLjUsIHNvIHdlIGRpdmlkZSBhbGwgdGhvc2UgZnJhbWVzIGJ5IDI1LiAKCjEuIDcuOTJzIHRvIDguOTJzCjEuIDEwLjZzIHRvIDExLjUycwoxLiAxNC4wOHMgdG8gMTUuMnMgCgpBbmQgcGxvdCB0aG9zZSEKCmBgYHtyfQpkYXRhIDwtIGRhdGEgJT4lCiAgcm93d2lzZSgpICU+JQogIG11dGF0ZShzZWNzID0gZ2F6ZV9wb2ludF9pbmRleC8xMjApCgpkYXRhICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5LCBjb2xvciA9IG1haW5ncm91cCwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIGdlb21fbGluZSgpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gNy45MiwgeG1heCA9IDguOTIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDEwLjYsIHhtYXggPSAxMS41MiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICB0aGVtZV9idygpCmBgYAoKTWF5YmUgZWFzaWVyIGlmIHdlIHNlcGFyYXRlIGdyb3VwcyBvZiBzaWduZXJzLiAKCmBgYHtyfQpkYXRhICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5LCBjb2xvciA9IG1haW5ncm91cCwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIGdlb21fbGluZShhbHBoYSA9IDAuNSkgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxNC4wOCwgeG1heCA9IDE1LjIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGZhY2V0X2dyaWQobWFpbmdyb3VwIH4gLikgKwogIHRoZW1lX2J3KCkgKwogIGd1aWRlcyhjb2xvciA9IEZBTFNFKQpgYGAKCk5leHQsIHdlJ3JlIGdvaW5nIHRvIGFkZCBBT0kgcG9zaXRpb24gaW5mb3JtYXRpb24uIFdlJ3JlIGdvaW5nIHRvIHB1bGwgaW4gaW5mb3JtYXRpb24gb24gc2lnbmVycycgcmlnaHQgaGFuZCBwb3NpdGlvbiAoYW5kIHRoZW4gYXBwbHkgdGhlIHNhbWUgaWRlYSB0byBvdGhlciBib2R5IHBhcnRzKS4gSSBzdWNjZXNzZnVsbHkgd3JvdGUgYSBmdW5jdGlvbiBjYWxsZWQgYGdldF94eV90aW1lc3RhbXBgIHRvIGRvIHRoaXMhIFlheS4gSSdtIGNodWZmZWQsIGFzIHRoZSBCcml0aXNoIHdvdWxkIHNheS4KCkxldCdzIHRyeSB0aGlzIG9uIFN0ZXBoYW5pZSdzIGRhdGEuIExldCdzIHNlZSBpZiB3ZSBjYW4gZmluZCBhIGNvcnJlbGF0aW9uIGJldHdlZW4gYW55IG9mIHRob3NlIGFuZCB0aGUgZXllIGdhemUgeS1wb3NpdGlvbi4gCgpgYGB7cn0KCiMgV2UgYWRkIG9uZSBtb3JlIHJvdyB0byB0aGUgeHlfdGltZXN0YW1wIGRhdGEgdG8gYWxpZ24gaXQgd2l0aCB0aGUgZW5kIG9mIHRoZSBleWUgZ2F6ZSBkYXRhLgpyaGFuZCA8LSBnZXRfeHlfdGltZXN0YW1wKCJhb2lfcG9zaXRpb24vQ2luZHlfYmVhcnNfRldfUG9zaXRpb24gb2YgUmlnaHQgSGFuZC50eHQiKSAlPiUKICBhZGRfcm93KHNlYyA9IDIxLjUsIHggPSA2NDAuMTYsIHkgPSAxMDU1Ljk3KQpsaGFuZCA8LSBnZXRfeHlfdGltZXN0YW1wKCJhb2lfcG9zaXRpb24vQ2luZHlfYmVhcnNfRldfUG9zaXRpb24gb2YgTGVmdCBIYW5kLnR4dCIpICU+JQogIGFkZF9yb3coc2VjID0gMjEuNSwgeCA9IDcwMy43NCwgeSA9IDEwNTguMzkpCm1vdXRoIDwtIGdldF94eV90aW1lc3RhbXAoImFvaV9wb3NpdGlvbi9DaW5keV9iZWFyc19GV19Qb3NpdGlvbiBvZiBtb3V0aCBzbWFsbC50eHQiKSAlPiUKICBhZGRfcm93KHNlYyA9IDIxLjUsIHggPSA2NTYuMzcsIHkgPSAzNzMuOTkpCgojIEdldCBTdGVwaGFuaWUncyBkYXRhCnN0ZXBoIDwtIGZpbHRlcihkYXRhLCBuYW1lID09ICJTdGVwaGFuaWUiKQoKc3RlcGggJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHkpKSArIAogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCksIGV4cGFuZCA9IGMoMCwwKSkgKyAKICBnZW9tX2xpbmUoYWxwaGEgPSAxLCBjb2xvciA9ICJwdXJwbGUiKSArIAogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gNy45MiwgeG1heCA9IDguOTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE0LjA4LCB4bWF4ID0gMTUuMiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBnZW9tX3N0ZXAoZGF0YSA9IHJoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogICMgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgIyBnZW9tX3N0ZXAoZGF0YSA9IG1vdXRoLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJibGFjayIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgIyBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIlJpZ2h0IEhhbmQiLCB4ID0gMywgeSA9IDEwMDAsIGNvbG9yID0gInJlZCIsIGFscGhhID0gMC41KSArCiAgIyBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIkxlZnQgSGFuZCIsIHggPSAzLCB5ID0gMTEwMCwgY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgIyBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIk1vdXRoIiwgeCA9IDMsIHkgPSAyMDAsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjUpICsKICBnZ3RpdGxlKCJTdGVwaGFuaWUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpKQoKc3RlcGggJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHkpKSArIAogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCksIGV4cGFuZCA9IGMoMCwwKSkgKyAKICBnZW9tX2xpbmUoYWxwaGEgPSAxLCBjb2xvciA9ICJwdXJwbGUiKSArIAogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gNy45MiwgeG1heCA9IDguOTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE0LjA4LCB4bWF4ID0gMTUuMiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiMgIGdlb21fc3RlcChkYXRhID0gcmhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiMgIGdlb21fc3RlcChkYXRhID0gbGhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGdlb21fc3RlcChkYXRhID0gbW91dGgsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsYWNrIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKIyBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIlJpZ2h0IEhhbmQiLCB4ID0gMywgeSA9IDEwMDAsIGNvbG9yID0gInJlZCIsIGFscGhhID0gMC41KSArCiMgIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTGVmdCBIYW5kIiwgeCA9IDMsIHkgPSAxMTAwLCBjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAwLjUpICsKICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIk1vdXRoIiwgeCA9IDMsIHkgPSAyNTAsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjUpICsKICBnZ3RpdGxlKCJTdGVwaGFuaWUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpKQoKc3RlcGggJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHkpKSArIAogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCksIGV4cGFuZCA9IGMoMCwwKSkgKyAKICBnZW9tX2xpbmUoYWxwaGEgPSAxLCBjb2xvciA9ICJwdXJwbGUiKSArIAogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gNy45MiwgeG1heCA9IDguOTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE0LjA4LCB4bWF4ID0gMTUuMiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZ2VvbV9zdGVwKGRhdGEgPSByaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKIyAgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBtb3V0aCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKIyAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJMZWZ0IEhhbmQiLCB4ID0gMywgeSA9IDExMDAsIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuNSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTW91dGgiLCB4ID0gMywgeSA9IDI1MCwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIlN0ZXBoYW5pZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpzdGVwaCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInB1cnBsZSIpICsgCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBnZW9tX3N0ZXAoZGF0YSA9IHJoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGdlb21fc3RlcChkYXRhID0gbGhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGdlb21fc3RlcChkYXRhID0gbW91dGgsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsYWNrIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIlJpZ2h0IEhhbmQiLCB4ID0gMywgeSA9IDEwMDAsIGNvbG9yID0gInJlZCIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJMZWZ0IEhhbmQiLCB4ID0gMywgeSA9IDExMDAsIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuNSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTW91dGgiLCB4ID0gMywgeSA9IDI1MCwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIlN0ZXBoYW5pZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKTm93IGxldCdzIHdvcmsgb24gY29ycmVsYXRpb25zLiBGaXJzdCwgb3VyIEFPSSB2ZWN0b3JzIGFyZSBub3QgdGhlIHNhbWUgc2l6ZSBhcyBvdXIgZXllIGdhemUgdmVjdG9ycywgYW5kIHRoZSB4L3kgcG9zaXRpb24gaXMgaXJyZWd1bGFybHkgc3BhY2VkIGFjcm9zcyB0aW1lIChpcnJlZ3VsYXJseSBzcGFjZWQga2V5IGZyYW1lcykuIApgYGB7cn0KIyBUaGUgZm9sbG93aW5nIGNvZGUgd2lsbCAiZXhwYW5kIiB0aGUgcmhhbmQgZGF0YSB2ZWN0b3JzIHRvIGZpdCB0aGUgbGVuZ3RoIG9mIFN0ZXBoYW5pZSdzIGRhdGEgdmVjdG9ycy4KdGltZV9pbmRleCA8LSBzdGVwaCRzZWNzCmNsb3Nlc3QgPC0gZnVuY3Rpb24oeCl7CiAgd2hpY2gubWluKGFicyh0aW1lX2luZGV4LXgpKQp9CgppbmRleF9sb2MgPC0gbWFwX2ludChyaGFuZCRzZWMsIGNsb3Nlc3QpCgpyaGFuZCA8LSBjYmluZChyaGFuZCwgdGltZV9pbmRleFtpbmRleF9sb2NdKSAlPiUKICBzZWxlY3QoLXNlYykgJT4lCiAgcmVuYW1lKHNlYyA9ICJ0aW1lX2luZGV4W2luZGV4X2xvY10iKSAlPiUKICBzZWxlY3Qoc2VjLCB4LCB5KQoKcmhhbmRfZnVsbCA8LSBzZWxlY3Qoc3RlcGgsIHNlY3MpICU+JQogIHJlbmFtZShzZWMgPSBzZWNzKSAlPiUKICBsZWZ0X2pvaW4ocmhhbmQpICU+JQogIGZpbGwoeCkgJT4lCiAgZmlsbCh5KSAlPiUKICBzbGljZSgxOihucm93KC4pLTEpKQoKcmhhbmRfZnVsbCA8LSByaGFuZF9mdWxsICU+JQogIGZpbHRlcihzZWMgPCByaGFuZCRzZWNbMTcyXSkgJT4lCiAgZmlsdGVyKHNlYyA+PSByaGFuZCRzZWNbMl0pCgpzdGVwaCA8LSBzdGVwaCAlPiUKICBmaWx0ZXIoc2VjcyA8IHJoYW5kJHNlY1sxNzJdKSAlPiUKICBmaWx0ZXIoc2VjcyA+PSByaGFuZCRzZWNbMl0pCgphIDwtIHJoYW5kX2Z1bGwkeQphIDwtIGFbMTpsZW5ndGgoYSktMV0gIyBTaG9ydGVuIGl0IGJ5IG9uZSBlbGVtZW50CmIgPC0gc3RlcGgkeQoKIyBUaGVuIHJ1biBjb3JyZWxhdGlvbnMKY29yKGEsYiwgdXNlID0gImNvbXBsZXRlLm9icyIpICMgYmFzaWMgY29ycmVsYXRpb24KdGhhdCA8LSBjY2YoYSxiLCBsYWcubWF4ID0gNDAwLCB0eXBlID0gImNvcnJlbGF0aW9uIiwgbmEuYWN0aW9uID0gbmEucGFzcywgcGxvdCA9IFQpICMgYXV0by1jb3JyZWxhdGlvbgpgYGAKCgpMZXQncyBzZXBhcmF0ZSBvdXQgaW5kaXZpZHVhbCBzaWduZXJzLiAKCmBgYHtyfQptYWtlX3NpZ25lcl9wbG90cyA8LSBmdW5jdGlvbihncm91cG5hbWUsIGxpbmVfY29sb3IpIHsKICBkYXRhICU+JQogIGZpbHRlcihtYWluZ3JvdXAgPT0gZ3JvdXBuYW1lKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKCkgKyAKICBnZW9tX2xpbmUoYWxwaGEgPSAxLCBjb2xvciA9IGxpbmVfY29sb3IpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gNy45MiwgeG1heCA9IDguOTIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDEwLjYsIHhtYXggPSAxMS41MiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBnZW9tX3N0ZXAoZGF0YSA9IHJoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGdlb21fc3RlcChkYXRhID0gbGhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGdlb21fc3RlcChkYXRhID0gbW91dGgsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsYWNrIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIlJpZ2h0IEhhbmQiLCB4ID0gMywgeSA9IDEwMDAsIGNvbG9yID0gInJlZCIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJMZWZ0IEhhbmQiLCB4ID0gMywgeSA9IDExMDAsIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuNSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTW91dGgiLCB4ID0gMywgeSA9IDIwMCwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKwogIGZhY2V0X2dyaWQobmFtZSB+IC4pICsKICBnZ3RpdGxlKGdyb3VwbmFtZSkgKwogIHRoZW1lX2J3KCkKfQoKbWFrZV9zaWduZXJfcGxvdHMoIkRlYWZFYXJseSIsICJyZWQiKQptYWtlX3NpZ25lcl9wbG90cygiRGVhZkxhdGUiLCAiZGFyayBncmVlbiIpCm1ha2Vfc2lnbmVyX3Bsb3RzKCJIZWFyaW5nTGF0ZSIsICJibHVlIikKbWFrZV9zaWduZXJfcGxvdHMoIkhlYXJpbmdOb3ZpY2UiLCAicHVycGxlIikKYGBgCgpPa2F5IHNvIHdpdGggRWFybHkgQVNMIG9idmlvdXNseSB2ZXJ5IHN0ZWFkeSBnYXplLiBOb3ZpY2VBU0wgaGFzIGxvdCBvZiBkb3duc2hpZnRzLiBTb21lIGFsaWduIHdpdGggc3BhdGlhbCByZWZlcmVuY2luZywgc29tZSBkbyBub3QuIFdlIG5lZWQgbW9yZSBvZiB0aGVtIChsZXQncyBsb29rIGF0IG90aGVyIHN0b3JpZXMgdyBiZXR0ZXIgZGF0YSkuIAoKCiMgTWlkYXMgRm9yd2FyZAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBHZXQgTWlkYXMgZGF0YQpkYXRhIDwtIHJlYWRfY3N2KCIuLi9BZHVsdCBEYXRhL3Jhd2RhdGEvbWlkYXNmdy5jc3YiKSAlPiUKICBjbGVhbl9uYW1lcygpICU+JQogIHJlbmFtZSh5ID0gZ2F6ZV9wb2ludF95X21jX3NweCwKICAgICAgICAgbGFuZ3VhZ2UgPSBsYW5ndWFnZV92YWx1ZSwKICAgICAgICAgbmFtZSA9IHBhcnRpY2lwYW50X25hbWUsCiAgICAgICAgIGdyb3VwID0gZ3JvdXBfdmFsdWUpCgojIFB1bGwgY2xlYW4gbmFtZXMgYW5kIGpvaW4gdG8gZGF0YQpjbGVhbm5hbWVzIDwtIHJlYWRfY3N2KCJwYXJ0bmFtZXMuY3N2IikgJT4lCiAgZGlzdGluY3QoKSAlPiUKICByZW5hbWUobmFtZSA9IHBhcnRpY2lwYW50KQoKZGF0YSA8LSBkYXRhICU+JSBsZWZ0X2pvaW4oY2xlYW5uYW1lcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtbmFtZSkgJT4lCiAgcmVuYW1lKG5hbWUgPSBuZXdfcGFydGljaXBhbnQpICU+JQogIGZpbHRlcighaXMubmEobmFtZSkpCgojIFB1bGwgZmluYWwgZ3JvdXAgYXNzaWdubWVudHMgYW5kIGpvaW4gdG8gZGF0YQpjbGVhbmdyb3VwcyA8LSByZWFkX2NzdigiZmluYWxkYXRhc2V0LmNzdiIpICU+JQogIHNlbGVjdChwYXJ0aWNpcGFudCwgbWFpbmdyb3VwKSAlPiUKICByZW5hbWUobmFtZSA9IHBhcnRpY2lwYW50KSAlPiUKICBkaXN0aW5jdCgpCgpkYXRhIDwtIGRhdGEgJT4lIGxlZnRfam9pbihjbGVhbmdyb3VwcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtZ3JvdXApCgojIExldCdzIGZpbmQgb3V0IHdobyB3YXMgTk9UIGluY2x1ZGVkIGluIFRocmVlIEJlYXJzCmV4Y2x1ZGVkIDwtIHJlYWRfY3N2KCJmaW5hbGRhdGFzZXQuY3N2IikgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50LCBtYWluZ3JvdXAsIHN0b3J5LCBkaXJlY3Rpb24sIGV5ZV9leGNsdWRlKSAlPiUKICBmaWx0ZXIoc3RvcnkgPT0gIktpbmdNaWRhcyIgJiBkaXJlY3Rpb24gPT0gImZvcndhcmQiKSAlPiUKICByZW5hbWUobmFtZSA9IHBhcnRpY2lwYW50KSAlPiUKICBzZWxlY3QobmFtZSwgZXllX2V4Y2x1ZGUpCgpkYXRhIDwtIGRhdGEgJT4lIGxlZnRfam9pbihleGNsdWRlZCwgYnkgPSAibmFtZSIpICU+JQogIGZpbHRlcighZXllX2V4Y2x1ZGUpICU+JQogIGZpbHRlcighaXMubmEoZXllX2V4Y2x1ZGUpKQoKZGF0YSAlPiUgc2VsZWN0KG5hbWUsIG1haW5ncm91cCkgJT4lIGRpc3RpbmN0KCkKYGBgCgpOb3cgbGV0J3MgZ3JhcGghISAKCkhtLiBPbmUgcGVyc29uIHNlZW1zIHdyb25nLiAKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIGdlb21fbGluZSgpICsgc2NhbGVfeV9yZXZlcnNlKCkKYGBgCk9rYXkgaXQncyBKZXNzZSdzIGRhdGEgdGhhdCBzZWVtcyBvZmYuIFdlJ2xsIHJlbW92ZSBoaW0gZm9yIG5vdyBhbmQgY29tZSBiYWNrIHRvIGl0LCBmaWd1cmUgb3V0IHdoeS4gCmBgYHtyfQpkYXRhICU+JSBmaWx0ZXIoZ2F6ZV9wb2ludF9pbmRleCA+IDMwMDAwKSAlPiUgc2VsZWN0KG5hbWUpICU+JSBkaXN0aW5jdCgpICU+JSBoZWFkKCkKYGBgCgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIGZpbHRlcihuYW1lICE9ICJKZXNzZSIpCgpkYXRhICU+JQogIGdncGxvdChhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5LCBjb2xvciA9IG1haW5ncm91cCwgZ3JvdXAgPSBuYW1lKSkgKyBnZW9tX2xpbmUoKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDQ1MDApKQpgYGAKCk5leHQgbGV0J3MgcGxvdCB0aGUgbW9tZW50cyB3aGVyZSBzcGF0aWFsIHJlZmVyZW5jaW5nIGhhcHBlbnMuIFRob3NlIGFyZSBmcmFtZXMKCjEuIDI0OCB0byA0MjcKMS4gNDYwIHRvIDUwOAoxLiA1MTIgdG8gNTYwCgpMaWtlIGJlZm9yZSwgd2UnbGwgY29udmVydCBnYXplcG9pbnRpbmRleCB0byBzZWNvbmRzIChieSBkaXZpZGluZyAxMjApIGFuZCBhbGwgZnJhbWVzIHRvIHNlY29uZHMgKGJ5IGRpdmlkaW5nIDI1KS4gCgoxLiA5LjkycyB0byAxNy4wOHMKMS4gMTguNHMgdG8gMjAuMzJzCjEuIDIwLjQ4cyB0byAyMi40cyAKCmBgYHtyfQpkYXRhIDwtIGRhdGEgJT4lCiAgcm93d2lzZSgpICU+JQogIG11dGF0ZShzZWNzID0gZ2F6ZV9wb2ludF9pbmRleC8xMjApCgpkYXRhICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5LCBjb2xvciA9IG1haW5ncm91cCwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDM3LjUpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA5LjkyLCB4bWF4ID0gMTcuMDgsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE4LjQsIHhtYXggPSAyMC4zMiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMjAuNDgsIHhtYXggPSAyMi40LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpCmBgYAoKTWF5YmUgZWFzaWVyIGlmIHdlIHNlcGFyYXRlIGdyb3VwcyBvZiBzaWduZXJzLiAKCmBgYHtyfQpkYXRhICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5LCBjb2xvciA9IG1haW5ncm91cCwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDM3LjUpKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDkuOTIsIHhtYXggPSAxNy4wOCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNCwgeG1heCA9IDIwLjMyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAyMC40OCwgeG1heCA9IDIyLjQsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGZhY2V0X2dyaWQobWFpbmdyb3VwIH4gLikKYGBgCgpJbmRpdmlkdWFsIHNpZ25lcnMuIAoKYGBge3J9CmRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkVhcmx5IikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGdyb3VwID0gbmFtZSkpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzcuNSkpICsKICBzY2FsZV95X3JldmVyc2UoKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInJlZCIpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOS45MiwgeG1heCA9IDE3LjA4LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxOC40LCB4bWF4ID0gMjAuMzIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDIwLjQ4LCB4bWF4ID0gMjIuNCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChuYW1lIH4gLikgKwogIGdndGl0bGUoIkRlYWZFYXJseSIpCgpkYXRhICU+JQogIGZpbHRlcihtYWluZ3JvdXAgPT0gIkRlYWZMYXRlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGdyb3VwID0gbmFtZSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAzNy41KSkgKwogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gImRhcmsgZ3JlZW4iKSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDkuOTIsIHhtYXggPSAxNy4wOCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNCwgeG1heCA9IDIwLjMyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAyMC40OCwgeG1heCA9IDIyLjQsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGZhY2V0X2dyaWQobmFtZSB+IC4pICsKICBnZ3RpdGxlKCJEZWFmTGF0ZSIpCgpkYXRhICU+JQogIGZpbHRlcihtYWluZ3JvdXAgPT0gIkhlYXJpbmdMYXRlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGdyb3VwID0gbmFtZSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAzNy41KSkgKwogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gImJsdWUiKSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDkuOTIsIHhtYXggPSAxNy4wOCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNCwgeG1heCA9IDIwLjMyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAyMC40OCwgeG1heCA9IDIyLjQsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGZhY2V0X2dyaWQobmFtZSB+IC4pICsKICBnZ3RpdGxlKCJIZWFyaW5nTGF0ZSIpCgpkYXRhICU+JQogIGZpbHRlcihtYWluZ3JvdXAgPT0gIkhlYXJpbmdOb3ZpY2UiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDM3LjUpKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAicHVycGxlIikgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA5LjkyLCB4bWF4ID0gMTcuMDgsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE4LjQsIHhtYXggPSAyMC4zMiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMjAuNDgsIHhtYXggPSAyMi40LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBmYWNldF9ncmlkKG5hbWUgfiAuKSArCiAgZ2d0aXRsZSgiSGVhcmluZ05vdmljZSIpCmBgYA==